#pragma once
#include <iostream>
#include <fcntl.h>
#include <sys/wait.h>
#include "../comm/commfun.hpp"
#include "../comm/log.hpp"

using namespace std;
using namespace ns_commfunc;

namespace ns_runner
{

    class Runner
    {
    public:
        Runner();
        ~Runner();

        static void closefd(int f1, int f2, int f3)
        {
            close(f1);
            close(f2);
            close(f3);
        }

        static int runner(const string& filename)
        {
            //只关心结果是否出现异常，结果正确与否交给上层判断
            //这里仅执行

            umask(0);
            int stdin_fd = open(PathUtil::filepath_stdin(filename).c_str(), O_CREAT | O_RDONLY, 0644);
            int stdout_fd = open(PathUtil::filepath_stdout(filename).c_str(), O_CREAT | O_WRONLY, 0644);
            int stderr_fd = open(PathUtil::filepath_stderr_runner(filename).c_str(), O_CREAT | O_WRONLY, 0644);

            if(stdin_fd < 0 || stdout_fd < 0 || stderr_fd < 0)
            {
                Log(Error, "运行时打开标准文件失败");
                return -1;
            }

            int id = fork();
            if(id < 0)
            {
                Log(Error, "运行时创建子进程失败");

                closefd(stdin_fd, stdout_fd, stderr_fd);
                return -2;
            }
            else if(id == 0)
            {
                dup2(stdin_fd, 0);
                dup2(stdout_fd, 1);
                dup2(stderr_fd, 2);

                execl(PathUtil::filepath_exe(filename).c_str(), PathUtil::filepath_exe(filename).c_str(), nullptr);
                exit(1);
            }
            else
            {
                int status = 0;
                waitpid(id, &status, 0);

                Log(Info, "运行完成");

                closefd(stdin_fd, stdout_fd, stderr_fd);
                return status & 0x7F;
            }
            
        }
    };
}
